﻿#region Use Directive
using System;
using System.Collections.Generic;
using System.Windows.Forms;


using System.IO;
using System.Management;

using Microsoft.SqlServer.Dts.Runtime;
using System.Drawing;

using System.Threading;
using System.Collections;
#endregion

namespace MSBIHelper
{
    public partial class MSBI : Form
    {
        PackageHelper ph = new PackageHelper();
        ManualResetEvent mreofd = new ManualResetEvent(false);

        public MSBI()
        {
            InitializeComponent();
        }

        public void RunCmd(string scmd)
        {
            System.Diagnostics.Process.Start("explorer", scmd);
        }

        private string[] getFiles(bool isFolder)
        { 
            string[] filenames = { };
            if (!isFolder)
            {
                if (openFileDialog1.ShowDialog().Equals(DialogResult.OK))
                {
                    filenames = openFileDialog1.FileNames;
                }
            }
            else
            {
                string pkgfolder = string.Empty;
                if (folderBrowserDialog1.ShowDialog().Equals(DialogResult.OK))
                    pkgfolder = folderBrowserDialog1.SelectedPath;
                else return filenames;
                filenames = Directory.GetFiles(pkgfolder, "*.dtsx", SearchOption.AllDirectories);
            }
            return filenames;
        }

        private string[] getFiles2(bool isFolder)
        {
            object filenames = new string[] { };
            mreofd.Reset();
            Thread thread = new Thread(
                o =>
                {
                    if (isFolder)
                        getFolderFiles(ref filenames);
                    else
                        getFiles(ref filenames);
                }
                );
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            mreofd.WaitOne();
            return (string[])filenames;
        }

        public void getFolderFiles(ref Object obj)
        {  
                string pkgfolder = string.Empty;
                if (folderBrowserDialog1.ShowDialog().Equals(DialogResult.OK))
                {
                    pkgfolder = folderBrowserDialog1.SelectedPath;
                    obj = Directory.GetFiles(pkgfolder, "*.dtsx", SearchOption.AllDirectories);
                }
            mreofd.Set();
        }
        public void getFiles(ref Object obj)
        {
            if (openFileDialog1.ShowDialog().Equals(DialogResult.OK))
            {
                obj = openFileDialog1.FileNames;
            }
            mreofd.Set();
        }
  
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                //check the file exists or not 
                if (!File.Exists(ph.DemoPackageName + ".dtsx"))
                    ph.CreateDemoPkg();

                rtbMsg.AppendText(string.Format("Package :{0} have done! please check!{1}",
                    ph.DemoPackageName, System.Environment.NewLine));
                //open the current Package path
                RunCmd(System.Windows.Forms.Application.StartupPath);

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            try
            {
                string [] filenames = getFiles2(chkboxChooseFolder.Checked);
                if (filenames.Length.Equals(0)) return;
                foreach (var filename in filenames)
                {
                    ph.addNotificationForOnePkg(filename, chkboxRemoveFormer.Checked);
                    rtbMsg.AppendText(string.Format("Package:{0} has been add Notification!{1}",
                        filename, System.Environment.NewLine));
                }      
                MessageBox.Show("Done! Add Send Notification!");
            }
            catch (Exception EX)
            {
                MessageBox.Show("Something Wrong! please Connect Administrator!");
                ph.SendMailToDeveloper(EX.Message+ Environment.NewLine+EX.StackTrace);
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {

            try
            {
                string[] filenames = getFiles2(chkboxChooseFolder.Checked);
                if(filenames.Length==0) return;
                foreach (var filename in openFileDialog1.FileNames)
                {
                    ph.RemoveNotificationForOnePkg(filename);
                    rtbMsg.AppendText(string.Format("Package:{0} has been remove Notification!{1}",
                    filename, System.Environment.NewLine));
                }
                MessageBox.Show("Done : remove OnError notification!");
            }
            catch (Exception ex)
            {
                MessageBox.Show("Sorry for this Exception, please  Connect Administrator!");
                ph.SendMailToDeveloper(ex.Message);
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            try
            { 
                string[] filenames = getFiles2(cbClFolder.Checked);
                foreach (var pkgpath in filenames)
                {
                    rtbChkList.AppendText(
                    ph.CheckList(pkgpath)
                    );
                    HeightFailRow(rtbChkList);
                }
                    #region old code
                    //Microsoft.SqlServer.Dts.Runtime.Application sqlPackageLoader = new Microsoft.SqlServer.Dts.Runtime.Application();
                    //Package p= sqlPackageLoader.LoadPackage(pkgpath, null);

                    //foreach (var item in p.Connections)
                    //{
                    //      rtbChkList.AppendText(
                    //               "name:"
                    //                + item.Name
                    //                + System.Environment.NewLine);
                    //       rtbChkList.AppendText(
                    //                "CreationName:"
                    //                + item.CreationName
                    //                + System.Environment.NewLine);
                    //      rtbChkList.AppendText(
                    //               "connectstring:"
                    //               + item.ConnectionString
                    //                + System.Environment.NewLine);
                    //}
                    //LogProviderEnumerator myEnum = p.LogProviders.GetEnumerator();
                    //while ((myEnum.MoveNext()) && (myEnum.Current != null))
                    //{
                    //    rtbChkList.AppendText(
                    //        "name: "
                    //    + myEnum.Current.Name
                    //        + System.Environment.NewLine);
                    //    rtbChkList.AppendText(
                    //     "configstring: "
                    // + myEnum.Current.ConfigString
                    //     + System.Environment.NewLine);
                    //}
                    //LoggingMode:Disabled
                    //p.LoggingOptions.SelectedLogProviders.Count.ToString()
                    #endregion
               
            }
            catch (Exception ex)
            {
                rtbChkList.AppendText(ex.Message);
            }

        }

        //check the fail info add red color of the fail rows
        private void HeightFailRow(RichTextBox rtb)
        {
            //Fail bold and italic Red show
            string sfail = "Fail!";
            int len = sfail.Length;
            int start = 0;
            while ((start = rtb.Text.IndexOf(sfail, start)) > 0)
            {
                rtb.Select(start, len);
                rtb.SelectionColor = Color.Red;
                rtb.SelectionFont = new Font(rtb.Font, rtb.Font.Style | FontStyle.Bold | FontStyle.Italic);
                start += len;
            }


        }

        private void button5_Click(object sender, EventArgs e)
        {
            try
            {
                string[] filenames = getFiles2(chkFolder.Checked);
                SerialWork(filenames);
            }
            catch (Exception EX)
            {
                MessageBox.Show(EX.Message);
            }
            
        }

        private void button6_Click(object sender, EventArgs e)
        {
            try
            { 
                string[] filenames = getFiles2(chkFolder.Checked);
                foreach (string pkgpath in filenames)
                {
                    ph.AddLogging(pkgpath);
                    rtbAuditFramework.AppendText(ph.ProcessInfo);
                    rtbAuditFramework.AppendText("Has been added Txt logging For Package:" + pkgpath);
                    rtbAuditFramework.AppendText(Environment.NewLine);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
              
        }

        private void button7_Click(object sender, EventArgs e)
        {
            try
            {
                string[] filenames = getFiles2(chkFolder.Checked);
                foreach (string pkgpath in filenames)
                {
                    try
                    {
                        Package p = ph.sqlPackageLoader.LoadPackage(pkgpath, null);
                        ph.RemoveLogging(p);
                        ph.sqlPackageLoader.SaveToXml(pkgpath, p, null);
                        rtbAuditFramework.AppendText(ph.ProcessInfo);
                        rtbAuditFramework.AppendText("Has been removed Txt logging For Package:" + pkgpath);
                        rtbAuditFramework.AppendText(Environment.NewLine);
                    }
                    catch (Exception ex)
                    {
                        rtbAuditFramework.AppendText(ex.Message);
                    }
                  
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button8_Click(object sender, EventArgs e)
        {
            try
            { 
                string[] filenames = getFiles2(chkFolder.Checked);
                foreach (string pkgpath in filenames)
                {
                    ph.AddAuditFramework(pkgpath, false);
                    rtbAuditFramework.AppendText(ph.ProcessInfo);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void button9_Click(object sender, EventArgs e)
        {
            try
            {
                string[] filenames = getFiles2(chkFolder.Checked);
                foreach (string pkgpath in filenames)
                {
                    Package p = ph.sqlPackageLoader.LoadPackage(pkgpath, null);
                    foreach (ConnectionManager  cm in p.Connections)
                    {
                        rtbChkList.AppendText("HostType:"+cm.HostType.ToString() + "\r\n");
                        rtbChkList.AppendText("Name:" + cm.Name + "\r\n");
                        rtbChkList.AppendText("CreationName:" + cm.CreationName + "\r\n");
                    }
                }
                //DataTable dt = new DataTable();
                //string connstr = "Data source=LocalHost;Provider=MSOLAP;Initial Catalog=Adventure Works DW 2008R2;";
                //string mdxScripts = "SELECT  NON EMPTY [Measures].[Order Count] ON 0,[Date].[Fiscal Year].MEMBERS ON 1 FROM [Adventure Works]";
                //using (AdomdConnection conn = new AdomdConnection(connstr))
                //{
                //    if (conn.State.Equals(ConnectionState.Closed))
                //        conn.Open();
                //    AdomdDataAdapter objDataAdapter = new AdomdDataAdapter(mdxScripts, conn);
                //    objDataAdapter.Fill(dt);
                //    conn.Close();
                //}
                //if (dt.Rows.Count > 0)
                //    MessageBox.Show("done");
                

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private string GetCPUUsage()
        {
            //try
            //{
            //    var searcher =
            //    new ManagementObjectSearcher
            //         (@"\\LocalHost\root\CIMV2",
            //          "select PercentProcessorTime from Win32_PerfFormattedData_Counters_ProcessorInformation where Name = \"_Total\""); 
            //    ManagementObjectCollection collection = searcher.Get();
            //    return string.Empty; 
            //}
            //catch (ManagementException e)
            //{
            //    MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
            //}
            return string.Empty;
        }

        public void SaveLogData()
        {
            string filename = DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".txt";
            File.AppendAllText(filename,rtbAuditFramework.Text);
        }

        private void button10_Click(object sender, EventArgs e)
        {
            string[] filenames = getFiles2(chkFolder.Checked);
                 List<string> errorfilelist = new List<string>();
                 HashSet<string> uniquefilelist = new HashSet<string>();
                 if (filenames.Length > 0)
                 rtbAuditFramework.AppendText(
                    "Has start to add Audit Framework :" 
                    + DateTime.Now.ToString()
                    +Environment.NewLine);
                 if (filenames.Length == 0) return;

             ParallelAuditFramework(filenames,uniquefilelist);
            #region ThreadPool
            //int currentcount = 1;
                 //AuditFramework[] afArray = new AuditFramework[filenames.Length];
                 //ManualResetEvent[] doneEvents = new ManualResetEvent[filenames.Length];
                 //DateTime st = DateTime.Now;
                 //foreach (string pkgpath in filenames)
                 //{
                 //    if (!uiquefilelist.Add(Path.GetFileName(pkgpath)))
                 //        continue;//if file exists then ignore this file
                 //    doneEvents[currentcount - 1] = new ManualResetEvent(false);
                 //    AuditFramework af = new AuditFramework(new ParaObject(pkgpath, cbisAudit.Checked), doneEvents[currentcount - 1],rtbAuditFramework);
                 //    afArray[currentcount - 1] = af;
                 //    ThreadPool.QueueUserWorkItem(af.ThreadPoolCallback,rtbAuditFramework);
                 //    currentcount++;
                 //}
                 //for (int j = 0; j < filenames.Length; j++)
                 //{
                 //    if (doneEvents[j] == null)
                 //        doneEvents[j] = new ManualResetEvent(true);
                 //}
                 //foreach (var wh in doneEvents) wh.WaitOne();
                 //rtbAuditFramework.AppendText(
                 //    "Has finished file count:" + filenames.Length
                 //    + " custum seconds:" +
                 //    (DateTime.Now - st).TotalSeconds
                 //    +Environment.NewLine
                 //    );
                 //rtbAuditFramework.AppendText(string.Format("unique file count :{0} \n", uiquefilelist.Count));
                 //if (filenames.Length > 0)
                 //    MessageBox.Show("all packages has been done!");
                 ////SaveLogData();
                 //Thread workthread1 = new Thread(
                 //     state =>
                 //     {
                 //         ph.AddAuditFramework2(new ParaObject(filenames[0], true));
                 //     }
            //    );
            #endregion

        }

        private void SerialWork(string[] filenames)
        { 
                ph.IsDbLog = chkbox_dblog.Checked ? true : false;
                int currentcount = 1;
                List<string> errorfilelist = new List<string>();
                HashSet<string> uiquefilelist = new HashSet<string>();
                if (filenames.Length > 0)
                    rtbAuditFramework.AppendText("Has start to add Audit Framework :"
                        + DateTime.Now.ToString()
                        + Environment.NewLine);
                foreach (string pkgpath in filenames)
                {
                    if (!uiquefilelist.Add(Path.GetFileName(pkgpath)))
                        continue;//if file exists then ignore this file
                    ph.AddAuditFramework(pkgpath, true);
                    rtbAuditFramework.AppendText(ph.ProcessInfo);
                    rtbAuditFramework.AppendText(
                        string.Format("{2} this is the {0} package, total packages: {1}\n",
                        currentcount++, filenames.Length, DateTime.Now));
                    rtbAuditFramework.ScrollToCaret();
                    if (ph.ProcessInfo.ToString().IndexOf("ErrorOccure") > -1)
                        errorfilelist.Add(pkgpath);
                }
                if (filenames.Length > 0)
                {
                    rtbAuditFramework.AppendText(Environment.NewLine);
                    rtbAuditFramework.AppendText("totoal file count:" + filenames.Length
                        + " unique file count:" + (filenames.Length - uiquefilelist.Count));
                }
                if (errorfilelist.Count > 0)
                {
                    rtbAuditFramework.AppendText(Environment.NewLine);
                    rtbAuditFramework.AppendText(string.Format("Error file count:{0} the Error file list is :\n",
                        errorfilelist.Count));
                    errorfilelist.ForEach(t => rtbAuditFramework.AppendText(t + Environment.NewLine));
                }

                if (filenames.Length > 0)
                    MessageBox.Show("all packages has been finished added audit framework!");
                SaveLogData();
            
        }

        private void ParallelAuditFramework(string[] filenames, HashSet<string> uiquefilelist)
        {
            //logical processer count + 2
            int workthreadcount = Environment.ProcessorCount + 2;   
            ManualResetEvent finishSignal = new ManualResetEvent(false);
            DateTime st = DateTime.Now;
            Queue<string> _queue = new Queue<string>(filenames);
            for (int i = 0; i < workthreadcount; i++)
            {
                Thread th = new Thread
                (
                    obj =>
                    {
                        while (true)
                        {
                            string pkgpath = string.Empty;
                            lock (((ICollection)_queue).SyncRoot)
                            {
                                if (_queue.Count == 0) { break; }
                                pkgpath = _queue.Dequeue();
                                if (!uiquefilelist.Add(Path.GetFileName(pkgpath)))
                                    continue;
                            }
                            AuditFramework af = new AuditFramework(new ParaObject(pkgpath, cbisAudit.Checked), rtbAuditFramework);
                            if (chkbox_dblog.Checked) af.SetLogDB();
                            af.DoAuditFrameWork();
                        }
                        finishSignal.Set();
                    }
                );
                th.Name = "WorkThread" + i.ToString();
                th.Start();
            }
            finishSignal.WaitOne();

            rtbAuditFramework.AppendText("Total File count:" + filenames.Length + Environment.NewLine);
            rtbAuditFramework.AppendText("Unique File count:" + uiquefilelist.Count + Environment.NewLine);
            string strmsg = "All files are finished, cusum time: " + (DateTime.Now - st).TotalSeconds + " seconds";
            MessageBox.Show(strmsg);
            rtbAuditFramework.AppendText(strmsg + Environment.NewLine);
            rtbAuditFramework.ScrollToCaret();
            SaveLogData(); 
        }

        private void ParallelNotification(string [] filenames)
        {
            int workthreadcount = Environment.ProcessorCount + 2;
            ManualResetEvent finishSignal = new ManualResetEvent(false);
            DateTime st = DateTime.Now;
            Queue<string> _queue = new Queue<string>(filenames);
            for (int i = 0; i < workthreadcount; i++)
            {
                Thread th = new Thread
                (
                    obj =>
                    {
                        while (true)
                        {
                            string pkgpath = string.Empty;
                            lock (((ICollection)_queue).SyncRoot)
                            {
                                if (_queue.Count == 0) { break; }
                                pkgpath = _queue.Dequeue(); 
                            }
                            AuditFramework af = new AuditFramework(new ParaObject(pkgpath,false), rtbMsg);
                            af.DoNotification();
                        }
                        finishSignal.Set();
                    }
                );
                th.Name = "WorkThread" + i.ToString();
                th.Start();
            }
            finishSignal.WaitOne();

            rtbMsg.AppendText("Total File count:" + filenames.Length + Environment.NewLine); 
            string strmsg = "All files are finished, cusum time: " + (DateTime.Now - st).TotalSeconds + " seconds";
            MessageBox.Show(strmsg);
            rtbMsg.AppendText(strmsg + Environment.NewLine);
            rtbMsg.ScrollToCaret();
            SaveLogData(); 
        }

        private void button11_Click(object sender, EventArgs e)
        {
            try
            {
                string[] filenames = getFiles2(cbCFolder.Checked);
                Dictionary<string, string> dict = new Dictionary<string, string>();
                foreach (string row in rtbVariables.Text.Split(
                    new char[]{'\r','\n'},
                    StringSplitOptions.RemoveEmptyEntries
                    ))
                {
                    if (row.IndexOf("$") == -1) continue;
                    if (dict.ContainsKey(row.Split('$')[0]))
                        dict[row.Split('$')[0]] = row.Split('$')[1];
                    else
                        dict.Add(row.Split('$')[0], row.Split('$')[1]);
                }
                foreach (var pkgpath in filenames)
                {
                    ph.UpdateVariables(pkgpath, dict);
                }
                
            }
            catch (Exception EX)
            {
                MessageBox.Show(EX.Message);
            }
           
            
        }

        private void button12_Click(object sender, EventArgs e)
        {
            try
            {
                string[] filenames = getFiles2(chkboxChooseFolder.Checked);
                if (filenames.Length.Equals(0)) return;
                ParallelNotification(filenames);
                MessageBox.Show("Done! Add Send Notification!");
            }
            catch (Exception EX)
            {
                MessageBox.Show("Something Wrong! please Connect Administrator!");
                ph.SendMailToDeveloper(EX.Message + Environment.NewLine + EX.StackTrace);
            }
        }

        //Create Configuration File for Package
        private void button13_Click(object sender, EventArgs e)
        {
            rtbVariables.Text = "";
            string[] filenames = getFiles2(chkboxChooseFolder.Checked);
            foreach (var pkgpath in filenames)
            {
                ph.AddConfiguration(pkgpath);
                rtbVariables.AppendText("has been add Configuration for Package:" 
                                        + pkgpath + Environment.NewLine);
                rtbVariables.AppendText(ph.ProcessInfo + Environment.NewLine);
                rtbVariables.ScrollToCaret();
            } 
        }

        private void button14_Click(object sender, EventArgs e)
        {
            string[] filenames = getFiles2(chkboxChooseFolder.Checked);
            foreach (var pkgpath in filenames)
            {
                ph.GenerateBatch(pkgpath);
                rtbVariables.AppendText("has generated batch file for Package:"
                                      + pkgpath + Environment.NewLine);
                rtbVariables.AppendText(ph.ProcessInfo);
                rtbVariables.AppendText(Environment.NewLine);
                rtbVariables.ScrollToCaret();
            } 
        }

        private void button15_Click(object sender, EventArgs e)
        {
            //write the think way down
            //jack said we need add a trim derived column for the source column
            //I think I could find the source control then add a derived column control
            //Just replace the old columns with Trim if the data type is DT_STR OR DT_WSTR
            //OR N_TEXT 
            string[] filenames = getFiles2(chkbx_folders.Checked);
            foreach (var filepath in filenames)
            {
                ph.AddTrimDerivedColumns(filepath);
            }
            if(filenames.Length>0)
                MessageBox.Show("finished");
        }


        
      
    }
}   